<?php
/**
 * Scan 个人理解，类似于mysql中的全表扫描。
 * 即使加上了过滤条件，因为没有利用上索引，所以无法避免全表扫描，速度会较慢。
 * author: JiangJun
 * CreateTime:2021/7/26 22:19
 */


require '../vendor/autoload.php';


use Aws\DynamoDb\Exception\DynamoDbException;
use Aws\DynamoDb\Marshaler;

$sdk = new Aws\Sdk([
    'region'   => 'us-west-2',
    'version'  => 'latest'
]);

$dynamodb = $sdk->createDynamoDb();

$marshaler = new Marshaler();

//Expression attribute values
$eav = $marshaler->marshalJson('
    {
        ":start_yr": 1950,
        ":end_yr": 1959
    }
');

$params = [
    'TableName' => 'Movies',
    'ProjectionExpression' => '#yr, title, info.rating',//查询哪些属性
    'FilterExpression' => '#yr between :start_yr and :end_yr',
    'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
    'ExpressionAttributeValues'=> $eav
];



//自己写的例子，查询评份在9以上的。能看出，filter并不需要一定含有主键。

$eav=$marshaler->marshalItem([
    ':r'=>9
]);

$params2 = [
    'TableName' => 'Movies',
    'ProjectionExpression' => '#yr, title, info.rating',//查询哪些属性
    'ExpressionAttributeNames'=> [ '#yr' => 'year' ],
    'FilterExpression' => 'info.rating > :r',
    'ExpressionAttributeValues'=> $eav,
    'Limit'=>500,//每次扫描的条数，不设置的话，就是1M。注意这个不是限制的返回条数
    'ReturnConsumedCapacity'=>'TOTAL'
];


echo "Scanning Movies table.\n";

/**
 * 如果扫描的结果集较多(大于1M)，会自动进行分页，也就是说一次取不完，只有多取几次才能取完。
 * 这里有疑问：我自己的例子中，取出来的结果，只有几末数据明显小于1M，但也分了2页
 * 上面疑问的答案是：不是看过滤后的数量是否大于1M，而是看是否扫描了1M。因为对于scan来说，不论是否有过滤，都是全表扫描，消耗的资源是一样的。
 */

try {
    $t=0;
    while (true) {
        $t++;
        echo PHP_EOL. "第{$t}次扫描" . PHP_EOL;
        //注意是用的scan方法，而不是query
        $result = $dynamodb->scan($params2);

        echo '本次扫描条数：' . $result['ScannedCount'] . PHP_EOL;
        echo '本次匹配条数：' . $result['Count'] . PHP_EOL;
        foreach ($result['Items'] as $i) {
            $movie = $marshaler->unmarshalItem($i);
            echo $movie['year'] . ': ' . $movie['title'];
            echo ' ... ' . $movie['info']['rating'] . "\n";
        }
        echo 'CapacityUnits:' .$result['ConsumedCapacity']['CapacityUnits'] . PHP_EOL;

        //只要存在LastEvaluatedKey，就表示还有数据没有取完。将这个参数，带入下一次的请求中，就能获取下一页的数据
        if (isset($result['LastEvaluatedKey'])) {
            $params2['ExclusiveStartKey'] = $result['LastEvaluatedKey'];
        } else {
            break;
        }
    }

} catch (DynamoDbException $e) {
    echo "Unable to scan:\n";
    echo $e->getMessage() . "\n";
}